﻿// <copyright file="DataUtility.cs" company="City of Portland, BES-ASM">
// </copyright>
// <summary>Network class</summary>

namespace BESASM.EMGAATS.DataAccess
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;

  /// <summary>
  /// Utility class for working with data values
  /// </summary>
  public static class DataUtility
  {
    /// <summary>
    /// Safely convert a data value from a database to a 32-bit integer
    /// </summary>
    /// <param name="dataValue">the data value to convert</param>
    /// <param name="defaultValue">The default integer value to return, if the value cannot be converted.</param>
    /// <returns>The data value as a double, or the defaultValue if the data value is DBNull or cannot be converted</returns>
    public static int SafeConvertInt32(object dataValue, int defaultValue = 0)
    {
      if (dataValue == DBNull.Value)
      {
        return defaultValue;
      }
      else
      {
        try
        {
          return Convert.ToInt32(dataValue);
        }
        catch
        {
          // TODO: Log error
          return defaultValue;
        }
      }
    }

    /// <summary>
    /// Safely convert a data value from a database to a double
    /// </summary>
    /// <param name="dataValue">The data value to convert</param>
    /// <param name="defaultValue">The default double value to return, if the value cannot be converted</param>
    /// <returns>The data value as a double, or the default value if the data value is DBNull or cannot be converted</returns>
    public static double SafeConvertDouble(object dataValue, double defaultValue = double.NaN)
    {
      if (dataValue == DBNull.Value)
      {
        return defaultValue;
      }
      else
      {
        try
        {
          return Convert.ToDouble(dataValue);
        }
        catch
        {
          // TODO: Log error
          return defaultValue;
        }
      }
    }

    /// <summary>
    /// Safely convert a data value from a database to a string
    /// </summary>
    /// <param name="dataValue">The data value to convert</param>
    /// <param name="defaultValue">The default string value to return if the data value is DBNull or cannot be converted</param>
    /// <returns>The data value as a string, or the default value if the data value is DBNull</returns>
    public static string SafeConvertString(object dataValue, string defaultValue = null)
    {
      if (dataValue == DBNull.Value)
      {
        return defaultValue;
      }
      else
      {
        return dataValue.ToString();
      }
    }

    /// <summary>
    /// Safely convert a data value from a database to a boolean
    /// </summary>
    /// <param name="dataValue">the data value to convert</param>
    /// <param name="defaultValue">The default boolean value to return if the data value is DBNull or cannot be converted</param>
    /// <returns>The data value as a boolean, or the default value if the data value cannot be converted</returns>
    public static bool SafeConvertBoolean(object dataValue, bool defaultValue = false)
    {
      if (dataValue == DBNull.Value)
      {
        return defaultValue;
      }
      else
      {
        try
        {
          return Convert.ToBoolean(dataValue);
        }
        catch
        {
          // TODO: Log error
          return defaultValue;
        }
      }
    }

    /// <summary>
    /// Safely convert a data value from a database to a DateTime
    /// </summary>
    /// <param name="dataValue">The data value to convert</param>
    /// <returns>The data value as a DateTime, or DateTime.MinValue if the data value cannot be converted</returns>
    public static DateTime SafeConvertDateTime(object dataValue)
    {
      return SafeConvertDateTime(dataValue, DateTime.MinValue);
    }

    /// <summary>
    /// Safely convert a data value from a database to a DateTime
    /// </summary>
    /// <param name="dataValue">The data value to convert</param>
    /// <param name="defaultValue">The default DateTime to return if the data value is DBNull or cannot be converted</param>
    /// <returns>The data value as a DateTime, or the default value fi the data value cannot be converted</returns>
    public static DateTime SafeConvertDateTime(object dataValue, DateTime defaultValue)
    {
      if (dataValue == DBNull.Value)
      {
        return defaultValue;
      }
      else
      {
        try
        {
          return Convert.ToDateTime(dataValue);
        }
        catch
        {
          return defaultValue;
        }
      }
    }

    /// <summary>
    /// Safely convert a data value from a database to an enumeration
    /// </summary>
    /// <typeparam name="T">The type of enumeration being parsed</typeparam>
    /// <param name="dataValue">The data value to convert</param>
    /// <param name="defaultValue">The default enum value to return if the data value is DBNull or cannot be converted</param>
    /// <returns>The data value as the specified enum, or the default value if the data value cannot be converted</returns>
    public static T SafeConvertEnum<T>(object dataValue, T defaultValue) where T : struct
    {
      bool parsed;
      return SafeConvertEnum<T>(dataValue, defaultValue, out parsed);
    }

    /// <summary>
    /// Safely convert a data value from a database to an enumeration
    /// </summary>
    /// <typeparam name="T">The type of enumeration being parsed</typeparam>
    /// <param name="dataValue">The data value to convert</param>
    /// <param name="defaultValue">The default enum value to return if the data value is DBNull or cannot be converted</param>
    /// <param name="parsed">A value indicating whether the dataValue was parsed from the dataValue. False if the dataValue was not defined in the Enum and the default value was returned.</param>
    /// <returns>The data value as the specified enum, or the default value if the data value cannot be converted</returns>
    public static T SafeConvertEnum<T>(object dataValue, T defaultValue, out bool parsed) where T : struct
    {
      parsed = false;

      if (!typeof(T).IsEnum)
      {
        throw new InvalidOperationException("This method can only to be used for enumerations.");
      }

      if (dataValue == DBNull.Value)
      {
        return defaultValue;
      }
      else
      {
        T enumValue;
        if (Enum.TryParse<T>(dataValue.ToString(), out enumValue))
        {
          if (Enum.IsDefined(typeof(T), enumValue))
          {
            parsed = true;
            return enumValue;
          }
          else
          {
            return defaultValue;
          }
        }
        else
        {
          return defaultValue;
        }
      }
    }
  }
}